import Products.Apple
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.Exception
import kotlin.random.Random

class TruckEvents {
    private val _sharedFlow: MutableSharedFlow<AbstractProduct> = MutableSharedFlow()
    private val scope: CoroutineScope = CoroutineScope(Job() + Dispatchers.Default)
    private val mutex: Mutex = Mutex()
    val sharedFlow: SharedFlow<AbstractProduct> = _sharedFlow.asSharedFlow()
    fun load(capacity: Double) {
        var tempProduct: AbstractProduct
        var currentCapacity: Double = 0.0
        scope.launch {
            mutex.withLock {
                try {
                    if (Store.products.size > 0) {
                        val productType: ProductSizeTypes = Store.products[0].productCategory.productSizeType
                        val products: MutableList<AbstractProduct> =
                            Store.products.filter { it.productCategory.productSizeType == productType }.toMutableList()
                        val productIterator = products.iterator()
                        tempProduct = productIterator.next()
                        var tempAmount: Int = 0
                        while (capacity >= currentCapacity && productIterator.hasNext()) {
                            if (tempProduct.amount == 0) {
                                productIterator.remove()
                                Store.products.remove(tempProduct)
                                tempProduct = productIterator.next()
                            }
                            tempAmount = tempProduct.amount - 1
                            tempProduct.amount = 1
                            currentCapacity += tempProduct.weight
                            _sharedFlow.emit(tempProduct)
                            tempProduct.amount = tempAmount
                            Store.currentCapacity -= tempProduct.weight
                            delay(tempProduct.shipmentDuration.toLong() * 1000)
                        }
                    }
                } catch (ex: Exception) {
                    scope.cancel()
                }
            }
            scope.cancel()
        }
    }

    fun unLoad(truck: AbstractTruck) {
        scope.launch {
            mutex.withLock {
                truck.unLoad()
                try {
                    truck.sharedFlow.collect { product ->
                        while (Store.currentCapacity >= Store.capacity) delay(100)
                        if (Store.products.any { it == product }) {
                            var tempProduct: AbstractProduct = Store.products[Store.products.indexOf(product)]
                            tempProduct.amount++
                        } else {
                            Store.products.add(product)
                        }
                        Store.currentCapacity += product.weight
                        println(
                            "---------Unloading Truck------------\n" +
                                    "${truck.model} ${product.productCategory.categoryName}\n" +
                                    "Amount of products in storage:${Store.products.size}\n" +
                                    "Current capacity: ${Store.currentCapacity}\n" +
                                    "------------------------------------"
                        )
                    }
                    scope.cancel()
                } catch (ex: Exception) {
                    scope.cancel()
                }
            }
        }
    }
}